/*
 * Copyright (C) 2018 Square, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.zlq.cn.util.logger;

import okhttp3.*;

import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * An OkHttp EventListener, which logs call events. Can be applied as an
 * {@linkplain OkHttpClient#eventListenerFactory() event listener factory}.
 *
 * <p>The format of the logs created by this class should not be considered stable and may change
 * slightly between releases. If you need a stable logging format, use your own event listener.
 *
 * @author sydata
 * @date 2020/10/24
 */
public final class LoggingEventListener extends EventListener {
    private final HttpLoggingInterceptor.Logger logger;
    private long startNs;

    private LoggingEventListener(HttpLoggingInterceptor.Logger logger) {
        this.logger = logger;
    }

    @Override
    public void callStart(Call call) {
        startNs = System.nanoTime();

        logWithTime("callStart: " + call.request());
    }

    @Override
    public void dnsStart(Call call, String domainName) {
        logWithTime("dnsStart: " + domainName);
    }

    @Override
    public void dnsEnd(Call call, String domainName, List<InetAddress> inetAddressList) {
        logWithTime("dnsEnd: " + inetAddressList);
    }

    @Override
    public void connectStart(Call call, InetSocketAddress inetSocketAddress, Proxy proxy) {
        logWithTime("connectStart: " + inetSocketAddress + " " + proxy);
    }

    @Override
    public void secureConnectStart(Call call) {
        logWithTime("secureConnectStart");
    }

    @Override
    public void secureConnectEnd(Call call, Handshake handshake) {
        logWithTime("secureConnectEnd: " + handshake);
    }

    @Override
    public void connectEnd(
            Call call, InetSocketAddress inetSocketAddress, Proxy proxy, Protocol protocol) {
        logWithTime("connectEnd: " + protocol);
    }

    @Override
    public void connectFailed(
            Call call,
            InetSocketAddress inetSocketAddress,
            Proxy proxy,
            Protocol protocol,
            IOException ioe) {
        logWithTime("connectFailed: " + protocol + " " + ioe);
    }

    @Override
    public void connectionAcquired(Call call, Connection connection) {
        logWithTime("connectionAcquired: " + connection);
    }

    @Override
    public void connectionReleased(Call call, Connection connection) {
        logWithTime("connectionReleased");
    }

    @Override
    public void requestHeadersStart(Call call) {
        logWithTime("requestHeadersStart");
    }

    @Override
    public void requestHeadersEnd(Call call, Request request) {
        logWithTime("requestHeadersEnd");
    }

    @Override
    public void requestBodyStart(Call call) {
        logWithTime("requestBodyStart");
    }

    @Override
    public void requestBodyEnd(Call call, long byteCount) {
        logWithTime("requestBodyEnd: byteCount=" + byteCount);
    }

    @Override
    public void requestFailed(Call call, IOException ioe) {
        logWithTime("requestFailed: " + ioe);
    }

    @Override
    public void responseHeadersStart(Call call) {
        logWithTime("responseHeadersStart");
    }

    @Override
    public void responseHeadersEnd(Call call, Response response) {
        logWithTime("responseHeadersEnd: " + response);
    }

    @Override
    public void responseBodyStart(Call call) {
        logWithTime("responseBodyStart");
    }

    @Override
    public void responseBodyEnd(Call call, long byteCount) {
        logWithTime("responseBodyEnd: byteCount=" + byteCount);
    }

    @Override
    public void responseFailed(Call call, IOException ioe) {
        logWithTime("responseFailed: " + ioe);
    }

    @Override
    public void callEnd(Call call) {
        logWithTime("callEnd");
    }

    @Override
    public void callFailed(Call call, IOException ioe) {
        logWithTime("callFailed: " + ioe);
    }

    private void logWithTime(String message) {
        long timeMs = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startNs);
        logger.log("[" + timeMs + " ms] " + message);
    }

    public static class Factory implements EventListener.Factory {
        private final HttpLoggingInterceptor.Logger logger;

        public Factory() {
            this(HttpLoggingInterceptor.Logger.DEFAULT);
        }

        public Factory(HttpLoggingInterceptor.Logger logger) {
            this.logger = logger;
        }

        @Override
        public EventListener create(Call call) {
            return new LoggingEventListener(logger);
        }
    }
}
